24 September, 2016

How to use this slides

The following single character keyboard shortcuts enable alternate display modes:

  • 'f' enable fullscreen mode
  • 'w' toggle widescreen mode
  • 'o' enable overview mode

Download the slides

Here (Right Click > Save As…)

大家的一些課前問題

  • 對於(資料)視覺化想得太簡單或太難
  • 覺得視覺化需要天生的設計美感?
  • 好的視覺化是不是主觀的?
  • 想實做自己的視覺化流程,但不知道如何開展,老是做到一半放棄
  • 用 Excel 辛苦做出的圖表,卻無法在下次重複使用
  • 導入視覺化工具,卻變成「純試試」,一點都不實用,造成導入的軟體無法發揮其效用

為什麼需要視覺化?

關於資料視覺化

  • 發現故事
  • 說服
  • 展示資料
  • 展示資料背後的故事
  • 做決策

EDA Process (Exploratory Data Analysis)

To Communicate

1854 年霍亂

John Snow 繪製了英國倫敦蘇活區的霍亂地圖,比對發現某一水井和感染者的居住地點相近,終於將汙染源鎖定在該水井,一周之後,市政府就封了這口水井,後來也證明霍亂是由汙水傳染而非一般認定的空氣傳染。

我們沒有太多偉大的目標

  • 報告給老闆、同事……
  • 讓相關的人做決策

"The simple graph has brought more information to the data analyst's mind than any other device." – John Tukey

資料視覺化,重點在「資料

資料視覺化思考範例:Anscombe's Quartet

經典資料集:Anscombe's Quartet

  • 4 x-y datasets
  • 相同的平均數和變異數 ── 從數字上完全看不出差異
  • 用甚麼方式可以看到差異?
#>    vars  n mean   sd median trimmed  mad  min   max range  skew kurtosis
#> x1    1 11  9.0 3.32   9.00    9.00 4.45 4.00 14.00 10.00  0.00    -1.53
#> x2    2 11  9.0 3.32   9.00    9.00 4.45 4.00 14.00 10.00  0.00    -1.53
#> x3    3 11  9.0 3.32   9.00    9.00 4.45 4.00 14.00 10.00  0.00    -1.53
#> x4    4 11  9.0 3.32   8.00    8.00 0.00 8.00 19.00 11.00  2.47     4.52
#> y1    5 11  7.5 2.03   7.58    7.49 1.82 4.26 10.84  6.58 -0.05    -1.20
#> y2    6 11  7.5 2.03   8.14    7.79 1.47 3.10  9.26  6.16 -0.98    -0.51
#> y3    7 11  7.5 2.03   7.11    7.15 1.53 5.39 12.74  7.35  1.38     1.24
#> y4    8 11  7.5 2.03   7.04    7.20 1.90 5.25 12.50  7.25  1.12     0.63
#>      se
#> x1 1.00
#> x2 1.00
#> x3 1.00
#> x4 1.00
#> y1 0.61
#> y2 0.61
#> y3 0.61
#> y4 0.61
x1 x2 x3 x4 y1 y2 y3 y4
10 10 10 8 8.04 9.14 7.46 6.58
8 8 8 8 6.95 8.14 6.77 5.76
13 13 13 8 7.58 8.74 12.74 7.71
9 9 9 8 8.81 8.77 7.11 8.84
11 11 11 8 8.33 9.26 7.81 8.47
14 14 14 8 9.96 8.10 8.84 7.04
6 6 6 8 7.24 6.13 6.08 5.25
4 4 4 19 4.26 3.10 5.39 12.50
12 12 12 8 10.84 9.13 8.15 5.56
7 7 7 8 4.82 7.26 6.42 7.91
5 5 5 8 5.68 4.74 5.73 6.89

資料視覺化思考範例:Anscombe's Quartet

  • 圖表可看到原本看不到的東西

視覺化之所以會讓人覺得很難

Tukey

  • Box Plot

Stephen Few

  • Dashboard

More Infographics and Design

要選擇什麼工具作圖?

要選擇什麼工具作圖

  1. 這張圖多重要?
  2. 可以花多少時間?值得花這麼多時間嗎?
  3. 有必要這要畫嗎?
  4. 這樣畫想要呈現什麼?

圖表也有分好壞

  • 評斷的標準是什麼?
  • 根據不同的理論可以擷取出上百種原則
  • 所以我們要掌握一些心法,讓我們選擇圖表時更簡單、專注

希望上完課後
大家都能把這個能力帶回去

ggplot2 in R 與繪圖心法

ggplot2 簡介

  • ggplot2 是一個很強大的資料探索及視覺化工具, 是許多最有影響力的 R 套件開發者 Hadley Wickham 所開發
  • 所有繪圖函數都有背後的視覺化邏輯(Grammar of Graphics

Grammar of Graphics 的作用就是幫助我們將圖表拆解成個別元素, 然後將這些元素按照邏輯個別操作,正確簡單地達到圖表的目的

It is far better to learn a language by actually speaking it!

一個例子學會畫圖:mpg 🚗油耗資料

mpg dataset:
Fuel economy data from 1999 and 2008 for 38 popular models of car.

variable detail
manufacturer 車廠
model 型號
displ 引擎排氣量
year 出廠年份
cyl 氣缸數
trans 自/手排
drv f = front-wheel drive, r = rear wheel drive, 4 = 4wd
cty city miles per gallon 城市駕駛油耗
hwy highway miles per gallon 高速公路駕駛油耗
fl 汽油: ethanol E85, diesel, regular, premium, CNG
class 車型

用圖表回答問題

  • 大引擎的車子更耗油嗎?如果是的話,那有多耗油?
  • 引擎大小和油耗效率之間的關係為何?正/負相關?線性/非線性?相關程度?

如果你給你老闆看這種表格

一個例子學會畫圖:mpg

先看兩個變數:

  1. displ - 引擎排氣公升
  2. hwy - (油耗效率,哩/加侖)

Scatterplots

library(ggplot2)
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy))

從圖表可歸納幾個結論:

  1. 兩變數為高度負相關 ── 大引擎 => 低效率
  2. 有些車是離群值

Exercise: 用 mpg 資料畫不同的圖

看看不同變數之間的相關

  • 畫出 scatterplot: hwy vs cyl
  • 畫出 scatterplot: class vs drv

Answer-1

## hwy vs cyl
ggplot(data = mpg) +
  geom_point(mapping = aes(x = hwy, y = cyl))

Answer-2

## class vs drv
ggplot(data = mpg) +
  geom_point(mapping = aes(x = class, y = drv))

Aesthetic Mapping

Aesthetic Mapping

  • Grammar of Graphics 裡面最重要的概念就是 Aesthetic Mapping
  • 在畫圖前我們先來練習用眼睛👀看 aethetics

Exercise: 觀察 Aesthetic Mapping

  • 有哪些變數 variables
  • 分別對應到哪個 aethetic

Aesthetics 基本題 1

  • x = displ
  • y = hwy
  • color = class

Aesthetic Mappings

在 x-y 二維的 Scatterplot 加入第三個 aesthetic

  • 把 class 對應到點的顏色
  • hint: ?geom_point: 查詢支援的 aesthetics

Aesthetic Mappings

  • x = displ
  • y = hwy
  • color = class
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy, color = class))

Aesthetics 基本題 2

  • x = displ
  • y = hwy
  • alpha (透明度) = class

Exercise

試試在 x-y 二維的 Scatterplot 加入第三個 aesthetic

  • 把 class 對應到點的alpha (透明度)
  • hint: ?geom_point: 查詢支援的 aesthetics

Answer

ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy, alpha = class))

Aesthetics 基本題 3

  • x = displ
  • y = hwy
  • shape = class

Exercise

試試在 x-y 二維的 Scatterplot 加入第三個 aesthetic

  • 把 class 對應到點的形狀

Answer

ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy, shape = class))
#> Warning: The shape palette can deal with a maximum of 6 discrete values
#> because more than 6 becomes difficult to discriminate; you have 7.
#> Consider specifying shapes manually if you must have them.
#> Warning: Removed 62 rows containing missing values (geom_point).
#> Warning: The shape palette can deal with a maximum of 6 discrete values
#> because more than 6 becomes difficult to discriminate; you have 7.
#> Consider specifying shapes manually if you must have them.

Aesthetic Mappings

ggplot(data = <DATA>) + # Data
  geom_<xxx>(
     mapping = aes(<MAPPINGS>), ##  <= Aesthetic mappings
     stat = <STAT>,
     position = <POSITION>
  ) +
  scale_<xxx>() + coord_<xxx>() + facet_<xxx>()
  theme_()
  • aes() 可以放在:
    • ggplot()裡面 – "記憶效果"(成為所有圖層預設帶入)
    • 外面 + aes()"記憶效果"(成為所有圖層預設帶入)
    • geom_<xxx>()裡面 – "記憶效果"(只對該 geom 有效)
  • geom_<xxx>(inherit.aes=FALSE): overrides the default aesthetics.

Static Aesthetic

有時候你可能只想要手動設定某個固定 aesthetic,這個例子的設定只為了美觀, 並不會帶出多餘資料訊息。

  • 將 aesthetic 放在 aes() 裡面: map aesthetic 並自動建立 legend
  • 將 aesthetic 放在 aes() 之外: 手動設定某個固定 aesthetic
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy), color = "blue")

Aesthetics: Perceptual Task

Aesthetics 不只這些

如何查?

  • ?geom_: 各 geom 有不同支援的 aesthetics

Visual Variable Accuracy

HW: 找圖觀察 Aesthetics

  • 上網 The Economist - Graphic detail 找 2 張圖或自己手上有的圖,找出 variable 對應的 aesthetic
  • 找出是否有多餘的對應(一個 variable 對多個 aesthetic)
    • ✘ 切忌畫蛇添足

Junk Colors

如何判斷好的圖表

一開始我們只要著重在圖表的資訊本身:

  1. 增加資訊
  2. 減少雜訊

Data-Ink Mazimazation

  1. 資訊在哪裡?
    • 資料本身相關的
    • 目的相關的
  2. 雜訊在哪裡?
    • 其他一切不相關的都先當作雜訊

消去不需要的元素

(附錄) How Data-Ink Maximazation

  1. 去除不必要的非資料物件
    • 去掉不必要的背景色彩
    • 去掉無意義的色彩變化
    • 淡化圖表格線
    • 去掉一切立體效果
  2. 弱化和統一剩下的非資料物件
    • 使用淡色的:座標軸、格線、表格線、填滿色
  3. 去除多於變數
    • 一個 x-y 方格 最多只留三個變數,一個畫面太多變數會影響資訊吸收
  4. 強調最重要的資料點
    • 標色

中場休息 ♨️

There are two main plotting functions in ggplot2:

  • qplot(): (quick plot) 需要快速畫圖時才使用,用法和 R 的內建繪圖函數 plot() 差不多
  • ggplot(): 推薦的繪圖方法,搭配繪圖步驟的其他函數逐步建構圖層

ggplot2 起手式

ggplot(data = <DATA>) + # Data
  geom_<xxx>(
     mapping = aes(<MAPPINGS>),
     stat = <STAT>,
     position = <POSITION>
  ) + # Layers & Aesthetic mappings
  scale_<xxx>() + coord_<xxx>() + facet_<xxx>() # Position
  theme_()

Data for Plot – ETL

資料和圖表是一體兩面,先有資料才有圖表

mpg 為例

  • mpg 共有 11 個變數 234 筆資料
  • 這裡需要的繪圖變數 (aesthetic mapping)
    • x: displ
    • y: hwy
#> # A tibble: 234 × 11
#>    manufacturer      model displ  year   cyl      trans   drv   cty   hwy
#>           <chr>      <chr> <dbl> <int> <int>      <chr> <chr> <int> <int>
#> 1          audi         a4   1.8  1999     4   auto(l5)     f    18    29
#> 2          audi         a4   1.8  1999     4 manual(m5)     f    21    29
#> 3          audi         a4   2.0  2008     4 manual(m6)     f    20    31
#> 4          audi         a4   2.0  2008     4   auto(av)     f    21    30
#> 5          audi         a4   2.8  1999     6   auto(l5)     f    16    26
#> 6          audi         a4   2.8  1999     6 manual(m5)     f    18    26
#> 7          audi         a4   3.1  2008     6   auto(av)     f    18    27
#> 8          audi a4 quattro   1.8  1999     4 manual(m5)     4    18    26
#> 9          audi a4 quattro   1.8  1999     4   auto(l5)     4    16    25
#> 10         audi a4 quattro   2.0  2008     4 manual(m6)     4    20    28
#> # ... with 224 more rows, and 2 more variables: fl <chr>, class <chr>

Geoms

Geoms

這兩張圖差在哪裡?

Geoms

  • Geom 決定圖表呈現的「幾何圖形物件」,也就是你眼睛看到的資料呈現方式
  • geom_<xxx>()
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy))

ggplot(data = mpg) +
  geom_smooth(mapping = aes(x = displ, y = hwy))

Layers 圖層觀念

要呈現多個幾何圖形物件 (Geoms) 時要怎麼做到呢?

  • 一個 geom_<xxx>() 就會在圖上畫一圖層 (Layer)
  • 一層層疊加上去
  • 每個圖層甚至可以用不同 data,在畫進階圖表時很常用到
  • 但要注意是否有預設的 aesthetic 不小心 mapping 到該圖層

Layers 圖層觀念

  • 兩層圖層
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy)) +
  geom_smooth(mapping= aes(x = displ, y = hwy))

Geoms

Geoms

  • 因為 Geoms 真的太多了,通常要用的時候再去查 cheatsheet
  • 如同前面所述,不同 Geoms 有不同支援的 Aesthetics

(附錄) Geoms – Cheatsheet

(附錄) Geoms – Cheatsheet

(附錄) Geoms – Cheatsheet

(附錄) Geoms – Cheatsheet

Stats

Bar Charts

  • 各種車型(class)的數量?
  • geom_bar()
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class))

在畫圖之前

你可能要先想到畫出這樣的表格:

class n
2seater 5
compact 47
midsize 41
minivan 11
pickup 33
subcompact 35
suv 62

表格與視覺化的關聯

  • 表格就是一種視覺化的方式,有時候一張好的表格資訊就很清楚
  • 畫圖只是將這些資訊再強調出來

Stats (Geom 的一體兩面)

  • stat_<xxx>()
  • 有些 Geom (例如 scatterplot) 畫的是 raw value (stat_identity)
  • 有些 Geom (例如 barplot)會計算新的 stat (e.g., count) 以供畫圖
  • 使用 geom_<xxx>() 時,要注意預設的 stat 是什麼

每個成功的 Geom 背後都有一個偉大的 Stat

stat = "identity" (不轉換)

Stats?

回頭來看 Aesthetic Mapping

  • x: class
  • y: ?? count 不在原本的 mpg 資料中

到底 count怎麼算出來的

  1. 原本可能在 Excel 算
  2. R 幫你算 dplyr::summarise()
  3. ggplot2 geom_bar 幫你算

?geom_bar 的預設 stat 是 "count"

stat = "count" 是怎麼幫你算出來的

先手動處理 stats 再畫圖

(有時候遇到複雜的問題就需要手動先算 Stats)

  • Plot bar chart with cut in dataset diamonds

dplyr::summarise() 算出 count 這個變數,再用 ggplot2 畫圖

hint: stat = "identity"

d <- mpg %>% 
  group_by(class) %>% 
  summarise(n = n())
d
#> # A tibble: 7 × 2
#>        class     n
#>        <chr> <int>
#> 1    2seater     5
#> 2    compact    47
#> 3    midsize    41
#> 4    minivan    11
#> 5     pickup    33
#> 6 subcompact    35
#> 7        suv    62

ggplot(data = d) +
  geom_bar(mapping = aes(x = class, y = n),
           stat = "identity")

Ecercise: 手動先算 Stats 再畫圖

  • 畫出各種車型(class)的平均油耗 bar chart

hint:

  • dplyr::group_by()
  • dplyr::summarise(mean(xxx)),
  • geom_bar(stat = "identity")
#> # A tibble: 7 × 2
#>        class mean_hwy
#>        <chr>    <dbl>
#> 1    2seater 24.80000
#> 2    compact 28.29787
#> 3    midsize 27.29268
#> 4    minivan 22.36364
#> 5     pickup 16.87879
#> 6 subcompact 28.14286
#> 7        suv 18.12903

沒有排序的 bar chart 很難看

  • 要怎麼排序?
  • reorder(<要排序的變數>, <參照大小>)
    *只能用在手動算的方式
d <- mpg %>% 
  group_by(class) %>% 
  summarise(n = n())
d
#> # A tibble: 7 × 2
#>        class     n
#>        <chr> <int>
#> 1    2seater     5
#> 2    compact    47
#> 3    midsize    41
#> 4    minivan    11
#> 5     pickup    33
#> 6 subcompact    35
#> 7        suv    62

ggplot(data = d) +
  geom_bar(mapping = aes(x = reorder(class, -n), y = n),
           stat = "identity")

Try Bar Charts

  • 填滿顏色 fill

(錯誤示範:不建議同一變數 mapping 多個 aes)

ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = class))

Geoms + Stats 實例

  • bar charts, histograms: 計算每一組 bin 裡面的數目.
ggplot(data = mpg, aes(x = class)) +
  geom_bar() +
  geom_text(stat = "count",
            aes(label = ..count.., y =..count..),
            vjust = "bottom")

Geoms + Stats 實例

  • 各種車型的油耗效率
  • boxplots: plot quartiles.
ggplot(data = mpg) +
  geom_boxplot(mapping = aes(x = class, y = hwy))

中場休息 ♨️

如何學習資料視覺化

從抄別人的圖表學起

  • 判斷圖表好壞之後,我們也要學會做好圖表
  • Google: "圖表名稱 + R"
  • 如果要用得順手,平常就要多看別人畫的好圖,要用時才知道從哪裡找起

Google 是學習畫圖的好朋友

  • 參見附錄 [視覺化資源整理]

Positions

Positions:當圖形在位置打架時要怎麼辦?

  • ?geom_bar
  • 堆疊:position = "stack" (default)
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "stack") +
  ggtitle('Position = "stack"')

Positions

position:

  • "identity" 同一位置(覆蓋住後面圖層)
  • "stack" 堆疊
  • "dodge" 併排
  • "fill" 堆疊並 scale 至 100%
  • "jitter" "抖…" 點會互相閃避

畫出各車廠(manufacturer)在不同車型(class)的數量為何?

Position = "identity"

  • 同一位置(覆蓋住後面圖層)
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "identity", alpha = .4) +
  ggtitle('Position = "identity"')

Position = "dodge"

  • 併排
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "dodge") +
  ggtitle('Position = "dodge"')

Position = "fill"

  • 堆疊並 scale 至 100%
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "fill") +
  ggtitle('Position = "fill"')

Facets

Too many variables!!!!

  • 看到剛才的車車油耗🚗,是不是覺得還是很難透過圖表理解資料?
  • 剛才畫的圖因為多了第3個變數,所以更難理解了

Facets: Small-Multiples

  • Facets 是很重要的一個呈現方式,一定要學起來
  • 為什麼要用 Facets?
    1. 當同一個座標平面塞入太多變數,會造成大腦無法負荷
    2. 分拆資訊,讓大腦協助腦補更有效率

"Illustrations of postage-stamp size are indexed by category or a label, sequenced over time like the frames of a movie, or ordered by a quantitative variable not used in the single image itself." – Edward Tufte

Exercise

畫出各車廠(manufacturer)在不同車型(class)的數量為何?

先用表格來思考

  • 你的(視覺化)表格要怎麼畫別人才會清楚?
  • 再思考把表格放到圖表上面?

三個變數應該怎麼放:

  • manufacturer
  • class
  • count

1. 老闆會叫你回去重做的表格

但卻是我們在 ggplot2 需要拿來畫圖的表格

#> Source: local data frame [32 x 3]
#> Groups: manufacturer [?]
#> 
#>    manufacturer      class     n
#>           <chr>      <chr> <int>
#> 1          audi    compact    15
#> 2          audi    midsize     3
#> 3     chevrolet    2seater     5
#> 4     chevrolet    midsize     5
#> 5     chevrolet        suv     9
#> 6         dodge    minivan    11
#> 7         dodge     pickup    19
#> 8         dodge        suv     7
#> 9          ford     pickup     7
#> 10         ford subcompact     9
#> 11         ford        suv     9
#> 12        honda subcompact     9
#> 13      hyundai    midsize     7
#> 14      hyundai subcompact     7
#> 15         jeep        suv     8
#> 16   land rover        suv     4
#> 17      lincoln        suv     3
#> 18      mercury        suv     4
#> 19       nissan    compact     2
#> 20       nissan    midsize     7
#> 21       nissan        suv     4
#> 22      pontiac    midsize     5
#> 23       subaru    compact     4
#> 24       subaru subcompact     4
#> 25       subaru        suv     6
#> 26       toyota    compact    12
#> 27       toyota    midsize     7
#> 28       toyota     pickup     7
#> 29       toyota        suv     8
#> 30   volkswagen    compact    14
#> 31   volkswagen    midsize     7
#> 32   volkswagen subcompact     6

2. 直接看就很清楚的表格

  • Pivot 樞紐分析表
manufacturer 2seater compact midsize minivan pickup subcompact suv
audi 0 15 3 0 0 0 0
chevrolet 5 0 5 0 0 0 9
dodge 0 0 0 11 19 0 7
ford 0 0 0 0 7 9 9
honda 0 0 0 0 0 9 0
hyundai 0 0 7 0 0 7 0
jeep 0 0 0 0 0 0 8
land rover 0 0 0 0 0 0 4
lincoln 0 0 0 0 0 0 3
mercury 0 0 0 0 0 0 4
nissan 0 2 7 0 0 0 4
pontiac 0 0 5 0 0 0 0
subaru 0 4 0 0 0 4 6
toyota 0 12 7 0 7 0 8
volkswagen 0 14 7 0 0 6 0

3. 讓視覺化增加資訊的清晰度

Facets

  • facet_wrap()

畫出各車廠(manufacturer)在不同車型(class)的數量 bar chart

  • x: class
  • y: count
  • fill 刪掉多餘的 mapping
  • facet: manufacturer
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class)) +
  facet_wrap( ~ manufacturer, ncol = 2)

Facets

  • 原則:一個座標平面(方格)最好不要超過三個變數
  • Don't overplotting
  • 拆出類別變數 (nominal) 放在個別的小方格 (facets)

當變數很多時 Faceting 就是你最好的朋友!

HW: Faceting 多變數

畫出各車廠(manufacturer)在不同車型(class)的
平均油耗效率(hwy) bar chart

hint:

  • dplyr::group_by(xxx, xxx)
  • dplyr::summarise(mean_hwy = mean(xxx))
  • geom_bar(stat = "identity")
  • facet_wrap()
#> Source: local data frame [32 x 3]
#> Groups: class [?]
#> 
#>      class manufacturer mean_hwy
#>      <chr>        <chr>    <dbl>
#> 1  2seater    chevrolet 24.80000
#> 2  compact         audi 26.93333
#> 3  compact       nissan 28.00000
#> 4  compact       subaru 26.00000
#> 5  compact       toyota 30.58333
#> 6  compact   volkswagen 28.50000
#> 7  midsize         audi 24.00000
#> 8  midsize    chevrolet 27.60000
#> 9  midsize      hyundai 27.71429
#> 10 midsize       nissan 27.42857
#> # ... with 22 more rows

來談談如何判別一個好的資料視覺化圖表

Junk Charts & Trifecta Checkup

Labels

Labels

圖表一定要有標題,別人才知道你要講的故事是什麼

  • ggtitle(), xlab(), ylab()
  • 組合技 – labs(): 各種標註(axis labels, legend titles, plot title/subtitle and below-plot caption)

Labels

標題

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() + 
  ggtitle("Fuel efficiency vs. Engine size")

標題 + 座標軸

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() + 
  ggtitle("Fuel efficiency vs. Engine size") +
  xlab("Engine displacement (L)") +
  ylab("Highway fuel efficiency (mpg)") 

標題 + 副標題 (Dev 版本) + Color (legend title)

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() + 
  labs(title = "Fuel efficiency vs. Engine size",
       subtitle = "Dataset: mpg",
       color = "Car Class")

Theme

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() +
  theme_bw()

ggplot2 內建 theme

Exercise: 試試看不同的 theme_*()

(附錄) Theme 相關套件

小結

ggplot2 的繪圖流程 (附錄)

ggplot2 的繪圖流程 (附錄)

  1. Data (noun/subject)
  2. Aesthetic mappings (adjectives): x, y, color, size, …
  3. Layers: Geom (verb), Stat (adverb)
  4. Position (preposition): Scales, Coord, Facet
  5. Theme

中場休息吃午餐 ♨️

視覺化流程總結

(非常重要!) (非常重要!) (非常重要!)

從結果(產出)倒回來想

  1. Issue: 這張圖表想解決的問題是什麼
  2. Geoms: 要畫什麼樣的圖
    • bar chart, line chart, heat map, …
  3. Variables: 需要那些變數?我的資料有這些變數嗎?
    • variables needed from the data
  4. Aesthetic Mapping
    • x:
    • y:

HW: 畫自己的圖

  • 找出一張平常會畫的圖表,以及其資料,填入上面格式
  • 試著用 ggplot2 畫出來~
    • 資料匯入
    • 資料前處理
    • 畫圖
    • 匯出成 png

R 的繪圖業障消除
很少人解,卻很關鍵的技巧

業障 1: 中文字型

Mac

ggplot2:

# 在最後加上
theme(text = element_text(family = "STHeiti"))

# 若有用到 geom_text 則要在裡面加 family = "STHeiti"
geom_text(family = "STHeiti")

輸出:

ggsave(device = "png", type = "cairo")`

Linux

基本上沒問題

Windows

基本上沒問題

業障 2: 如何匯入資料

業障 3: Export Plots 如何匯出圖表

p <- ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() +
  theme_bw()

## ggplot 匯出專用
ggsave(p,
       filename = "my_plot.png",
       device = "png", h = 2, w = 3, type = "cairo")
# system(paste("open my_plot.png"))

或用

png(filename = "my_plot.png",
    h = 2, w = 3, type = "cairo")  # 開啟繪圖 device (這裡用的是 png)
plot(p)    # 開始畫圖
dev.off()  # 關閉繪圖 device

Export Plots 匯出圖表

ggplot2 進階操作與延伸應用

Scales

scale_<aes>_<屬性>()

  • 有時候各 Aes 自動產生的 Scale 看起來很糟(區間不對、單位不對、顏色不對, …)
  • 這時需要調整 Aes 的 Scale
<aes> Description
x x position and coordinate
y y position and coordinate
colour Color of lines and points
fill Color of area fills (e.g. bar graph)
linetype Solid/dashed/dotted lines
shape Shape of points
size Size of points
alpha Opacity/transparency

<屬性> Description
hue Equally-spaced colors from the color wheel
manual Manually-specified values (e.g., colors, point shapes, line types)
gradient Color gradient
grey Shades of grey
discrete Discrete values (e.g., colors, point shapes, line types, point sizes)
continuous Continuous values (e.g., alpha, colors, point sizes)

Scales – 數值型座標

scale_*_continuouts()

  • breaks 刻度 (tick-breaks)
    • breaks: 刻度向量
    • minor_breaks 副格線
  • labels 標籤文字
    • A character vector giving labels (must be same length as breaks)
    • A function that takes the breaks as input and returns labels as output
      scales 套件 (千分位comma(), 錢號dollar(), 單位unit_format, …)
  • limits 最大最小值
    • c(最小值, 最大值). (Use NA to refer to the existing minimum or maximum.)

Scales – 數值型座標

library(ggplot2movies) # IMDB data
movies

Scales – 數值型座標

Scales – 數值型座標

library(ggplot2movies) # IMDB data
d <- movies %>% filter(votes > 1000) # 篩選投票數 1,000 以上的電影
m <- ggplot(d, aes(rating, votes)) +
  geom_point(na.rm = TRUE)
m

#  * change the axis labels
m + scale_y_continuous("number of votes")

#  * 千分逗號
m + scale_y_continuous(labels = scales::comma)

#  * modify the tick-breaks
m + scale_x_continuous(breaks = c(0:10))

#  * manually label the ticks
m + scale_x_continuous(breaks = c(2,5,8), 
                       labels = c("2 (horrible)", "5 (ok)", "8 (awesome)"))

#  * modify the axis limits
m + scale_y_continuous(limits = c(0, 5000)) +
    scale_x_continuous(limits = c(7, 8))

Scales – 日期座標

scale_x_date(date_breaks = <date breaks>, 
             date_labels = "'%y-%m")
  • date_breaks: 時間間隔 "2 weeks", "10 years", …
  • date_labels: 時間格式?strptime。可查詢 date_labels的時間格式怎麼寫

Scales – 日期座標

# 美國總統資料
presidential
#> # A tibble: 11 × 4
#>          name      start        end      party
#>         <chr>     <date>     <date>      <chr>
#> 1  Eisenhower 1953-01-20 1961-01-20 Republican
#> 2     Kennedy 1961-01-20 1963-11-22 Democratic
#> 3     Johnson 1963-11-22 1969-01-20 Democratic
#> 4       Nixon 1969-01-20 1974-08-09 Republican
#> 5        Ford 1974-08-09 1977-01-20 Republican
#> 6      Carter 1977-01-20 1981-01-20 Democratic
#> 7      Reagan 1981-01-20 1989-01-20 Republican
#> 8        Bush 1989-01-20 1993-01-20 Republican
#> 9     Clinton 1993-01-20 2001-01-20 Democratic
#> 10       Bush 2001-01-20 2009-01-20 Republican
#> 11      Obama 2009-01-20 2017-01-20 Democratic

d <- presidential %>%
  mutate(id = 33 + row_number())  # id: 屆數

ggplot(d, aes(x = start, y = id)) +
  geom_point() +
  geom_segment(aes(xend = end, yend = id)) +
  geom_text(aes(label = name), hjust = 0,  vjust = 0, nudge_y = 0.2) +
  scale_x_date(NULL, breaks = presidential$start, date_labels = "'%y")

Scales – 離散型座標 (很少用到)

scale_*_discrete()

p <- ggplot(diamonds, aes(cut)) + geom_bar()

# * 客制化標籤
p + scale_x_discrete("Cut", 
                     labels = c("Fair" = "F",
                                "Good" = "G",
                                "Very Good" = "VG",
                                "Perfect" = "P",
                                "Ideal" = "I"))

# * Use limits to adjust the which levels (and in what order)
# are displayed
p + scale_x_discrete(limits=c("Fair","Ideal"))
#> Warning: Removed 30779 rows containing non-finite values (stat_count).

# 也可以直接用座標來調
# p + xlim("Fair","Ideal", "Good")
# p + ylim("I1", "IF")

中場休息 ♨️

Colors

Preattentive Processing

顏色是很強大的工具

  • 低精準性(較難透過顏色判斷數值)
  • 但是很能吸引注意力

Feature Hierarchy

調顏色要注意的地方

  • 沒事別亂調顏色,有需要再改
  • 要調顏色的話等到最後再動

Scale Color and Fill

離散型資料 vs 連續型資料

Scale Color and Fill – 離散型

Scale Color and Fill – Manual (手動填色)

d <- presidential %>%
  mutate(id = 33 + row_number())

ggplot(d, aes(start, id, colour = party)) +
  geom_point() +
  geom_segment(aes(xend = end, yend = id)) +
  geom_text(aes(label = name), hjust = 0,  vjust = 0, nudge_y = 0.2) +
  scale_x_date(NULL, breaks = presidential$start, date_labels = "'%y") +
  scale_colour_manual(values = c(Republican = "Red", Democratic = "Blue"))

Text Labeling

Text Labeling

Exercise: 在剛才畫的 dot plot 標註各"車型"油耗效率最佳的車

library(dplyr)
library(ggplot2)

mpg %>%
  group_by(class) %>%
  mutate(rank = row_number(desc(hwy))) %>% 
  arrange(class, rank, hwy) %>% 
  View
## 各"車型"油耗效率最佳的車
best_in_class <- mpg %>%
  group_by(class) %>%
  filter(row_number(desc(hwy)) == 1)

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point(aes(colour = class)) +
  geom_text(aes(label = model), data = best_in_class)

Text Labeling

  • ggrepel - 自動計算標註文字的位置

Sometimes labeling on dots is not an easy work when plottng, especially when you have lots of dots in you plotting area.

  • use geom_text_repel() instead of geom_text()

動態圖表

ggplot to Plotly 簡單製作動態圖表

Plotly

只需要一行神奇的指令!

library(plotly)
p <- ggplot() + ...
ggplotly(p)  # 神奇的指令

Excercise: 請把下面的圖變成動態圖表

p <- ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, color = class))

報告製作
with R Markdown

R Markdown

終極應用一條龍用 R 做報告

R Markdown

  • Markdown 語法
所有換段都必須空一行!!!
所有換段都必須空一行!!!
所有換段都必須空一行!!!

不想換段但想強制換行在後面用兩個空白__

# 大標
## 中標
### 小標

- Bullet Point
- Bullet Point

1. 有序
2. 有序

[連結](url)
![圖片說明](img)

*斜體*
**粗體**
***斜粗體***

R Markdown

中場休息 ♨️

R Markdown Template

有很多別人開發好的漂亮套版可以直接拿來用, 今天要教的是 prettydoc 這個套件

  1. Install prettydoc. install.packages("prettydoc")
  2. New File > R Markdown > From Template
  3. Choose "Light Weight and Pretty Document (HTML) {prettydoc}"

視覺化應用

Map 畫地圖

Example: 地圖視覺化 – Leaflet

Data Man【畫地圖時最需要注意的地方:人口密度可能欺騙眼睛】

在畫地圖的時候,最需要記得的一件事是:人口密度高的地方,發生某種事件的次數應該也會高。比方說,我們要畫全台灣的寵物走失地圖,因為台北市人口密度高,因此每單位面積寵物隻數,理當比苗栗縣來得高(先不考慮台北市和苗栗縣民誰比較愛養寵物),因此寵物走失的隻數應該也會比較多。

如果把寵物走失密度化成地圖,就會出現台北市的顏色很深,苗栗顏色較淺的情況。但這並不代表台北市的寵物比較容易走失,只是反映兩地的人口密度不同。不過,較沒經驗的繪圖者和讀者,可能就會從這張地圖得出「台北市寵物比較容易走失」的結論,犯下我們今天分享的漫畫中的人一樣的錯誤。

因此,在繪製密度地圖的時候,一定要先想到:我們利用的數據跟人口密度有無相關性,有的話,要怎麼排除人口密度的影響,才能從地圖中找出數據真正埋藏的故事。

Reference

Resources 視覺化資源整理

Data Cleansing (ETL)

  • dplyr
  • tidyr
  • broom

ggplot2 Cookbook and Documentation

ggplot2 延伸套件

ggplot2 延伸套件整理

Cheatsheet

Other Viz Packages

  • sjPlot: 快速繪製統計模型和表格 (html output)
  • sjmisc: Utility and recode functions for R and sjPlot. 處理問卷 variable, label, spss file, …
  • dygraphs: (RStudio) 動態繪製 time-series data
  • leaflet: Leaflet 地圖
  • ggvis: (hadley) 動態圖表,可搭配 Shiny,尚未有完整應用體系
  • rCharts: (停止開發很久) 動態圖表

R Plot Galleries

Other Plot Galleries

視覺化心法

最後

作業

  • 找圖觀察 Aesthetics
  • 先手動處理 stats 再畫圖
  • Faceting 多變數
  • 畫自己的圖
  • 用 Rmd 做自己的報告

課後問卷